#include <stdint.h>
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include "function_interface.h"
#include "TableInterface/param_table_interface.h"
#include "fpga_interface.h"
#include "ratio_coef.h"
#include "temp_sample.h"
#include "electricity_quantity_statistics.h"
#include "comm_monitor.h"
#include "version.h"
#include "TableInterface/upper_table_interface.h"
#include "dataBase/miscStaticDataFunction.h"
#include "popen_interface.h"
#include "iso_interface.h"
#include "pulse_operate.h"
#include "misc.h"
#include "utils.h"
#include "logInterface.h"
#include "debug.h"
#include "ieee_1547.h"
#include <syslog.h>
#include "table_refresh.h"
#include "net_param.h"
#include "config_interface.h"
#include <sys/time.h>
#include "global_variable.h"
#include "table_refresh.h"


static int FuncInf_IsForbidTurnOn(void)
{
    uint16_t state, i, j, subType;
    bool forbid = false;

    /* 存在ARM故障 */
    for(j = 0; j < 3; j++)
    {
        FpgaInf_Read(FPGA_ADDR_ARM_FAULT_REG_BEGIN + j, &state);
        for(i = 0; i < 16; i++)
        {
            if(GET_BIT(state, i))
            {
                forbid = true;
                subType = 100 + j * 16 + i;
                logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_SYS_TIP, subType, COM_DATA_TYPE_NONE, NULL);
                syslog(LOG_INFO, "%s: Forbid Turn on: State%d[%d]", __func__, 13 + j, i);
            }
        }
    }

    return (forbid == true ? 1 : 0);
}


static int FuncInf_ClearAppointPwr(void)
{
    if(FpgaInf_Write(26, 0) != 0)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }
    if(FpgaInf_Write(27, 0) != 0)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    return 0;
}


static int FuncInf_SetupZeroCalibration(void)
{
    uint16_t idx, u16Val;

    for(idx = 0; idx < 16; idx++)
    {
        if(FuncInf_DirectReadFpga(FPGA_ADDR_RD_ZERO_CAL_BEGIN + idx, &u16Val) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN();
            return -1;
        }
        if(FuncInf_DirectWriteFpga(FUNCINF_OPERATOR_UPPER, FPGA_ADDR_WR_ZERO_CAL_BEGIN + idx, u16Val) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN();
            return -1;
        }
    }

    return 0;
}


static int FuncInf_CancelZeroCalibration(void)
{
    uint16_t idx;

    for(idx = 0; idx < 16; idx++)
    {
        if(FuncInf_DirectWriteFpga(FUNCINF_OPERATOR_UPPER, FPGA_ADDR_WR_ZERO_CAL_BEGIN + idx, 0) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN();
            return -1;
        }
    }

    return 0;
}


#if 1
static char *strCmder[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_OPERATOR_TABLE
#undef X_MACRO    
};


static char *strLmtType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_LMT_TYPE_TABLE
#undef X_MACRO  
};


static char *strCmdIdx[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_CMD_IDX_TABLE
#undef X_MACRO  
};


static char *strBitIdx[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_BIT_IDX_TABLE
#undef X_MACRO  
};


static char *strThrshdType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_THRSHD_TYPE_TABLE
#undef X_MACRO  
};


static char *strAppointType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_APPOINT_TYPE_TABLE
#undef X_MACRO  
};


static char *strLamp[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_LAMP_TABLE
#undef X_MACRO  
};


static char *strTurn[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_TURN_TABLE
#undef X_MACRO  
};


static char *strRatioCoefType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_RATIO_COEF_TYPE_TABLE
#undef X_MACRO  
};


static char *strNetParamType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_NET_PARAM_TYPE_TABLE
#undef X_MACRO  
};


static char *strExtrValType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_EXTR_VAL_TYPE_TABLE
#undef X_MACRO  
};


static char *strTestSwitchType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_TEST_SWITCH_TYPE_TABLE
#undef X_MACRO  
};


static char *strCommSwitchType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_COMM_SWITCH_TYPE_TABLE
#undef X_MACRO  
};


static char *strStrtgSwitchType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_STRTG_SWITCH_TYPE_TABLE
#undef X_MACRO  
};

static char *strConfigSwitchType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_CONFIG_SWITCH_TYPE_TABLE
#undef X_MACRO  
};


static char *strArmThrType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_ARM_THR_TYPE_TABLE
#undef X_MACRO  
};


static char *strPeriodParamType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_PERIOD_PARAM_TYPE_TABLE
#undef X_MACRO  
};


static char *str1547ParamType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_1547_PARAM_TYPE_TABLE
#undef X_MACRO  
};


static char *strDbgValIdx[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_DBG_VAL_IDX_TABLE
#undef X_MACRO  
};


static char *strTimeType[] =
{
#define X_MACRO(a, b) #a,
    FUNCINF_TIME_TYPE_TABLE
#undef X_MACRO  
};
#endif


#if 1
/**
 * @brief 直读FPGA
 */
funcInfErr_t FuncInf_DirectReadFpga(uint32_t addr, uint16_t *pValue)
{
    if(addr >= FPGA_ADDR_MAX)
    {
        PRINT_WARN("addr[%d]", addr);
        return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取电压
 */
funcInfErr_t FuncInf_GetVoltage(funcInfVolType_t volType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(volType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_VOL_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("volType[%d]", volType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(volType)
    {
        case FUNCINF_VOL_TYPE_PHASE_A:
            addr = FPGA_ADDR_VOL_TYPE_PHASE_A;
            break;

        case FUNCINF_VOL_TYPE_PHASE_B:
            addr = FPGA_ADDR_VOL_TYPE_PHASE_B;
            break;

        case FUNCINF_VOL_TYPE_PHASE_C:
            addr = FPGA_ADDR_VOL_TYPE_PHASE_C;
            break;

        case FUNCINF_VOL_TYPE_BUS:
        case FUNCINF_VOL_TYPE_DC:
            addr = FPGA_ADDR_VOL_TYPE_DC;
            break;

        case FUNCINF_VOL_TYPE_BAT:
            addr = FPGA_ADDR_VOL_TYPE_BAT;
            break;

        default:
            PRINT_WARN("volType[%d]", volType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取电流
 */
funcInfErr_t FuncInf_GetCurrent(funcInfCurType_t curType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(curType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CUR_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", curType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(curType)
    {
        case FUNCINF_CUR_TYPE_PHASE_A:
            addr = FPGA_ADDR_CUR_TYPE_PHASE_A;
            break;

        case FUNCINF_CUR_TYPE_PHASE_B:
            addr = FPGA_ADDR_CUR_TYPE_PHASE_B;
            break;

        case FUNCINF_CUR_TYPE_PHASE_C:
            addr = FPGA_ADDR_CUR_TYPE_PHASE_C;
            break;

        case FUNCINF_CUR_TYPE_BUS:
        case FUNCINF_CUR_TYPE_DC:
            addr = FPGA_ADDR_CUR_TYPE_DC;
            break;

        case FUNCINF_CUR_TYPE_BAT:
            addr = FPGA_ADDR_CUR_TYPE_BAT;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", curType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取功率
 */
funcInfErr_t FuncInf_GetPower(funcInfPwrType_t pwrType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(pwrType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_PWR_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", pwrType);
            return -FUNCINF_ERR_PARAM;
    }

    if(pwrType == FUNCINF_PWR_TYPE_APPARENT)
    {
        float actPwr, reactPwr;

        addr = FPGA_ADDR_PWR_TYPE_ACT;

        if(FpgaInf_Read(addr, &fpgaVal) != 0)
        {
            PRINT_WARN();
            return -FUNCINF_ERR_READ;
        }

        if(RatioCoef_GetRealValue(addr, fpgaVal, &actPwr) != 0)
        {
            PRINT_WARN();
            return -FUNCINF_ERR_CONVERT;
        }

        addr = FPGA_ADDR_PWR_TYPE_REACT;

        if(FpgaInf_Read(addr, &fpgaVal) != 0)
        {
            PRINT_WARN();
            return -FUNCINF_ERR_READ;
        }

        if(RatioCoef_GetRealValue(addr, fpgaVal, &reactPwr) != 0)
        {
            PRINT_WARN();
            return -FUNCINF_ERR_CONVERT;
        }

        *pValue = sqrt(actPwr * actPwr + reactPwr * reactPwr);
        return FUNCINF_ERR_NONE;
    }

    switch(pwrType)
    {
        case FUNCINF_PWR_TYPE_ACT:
            addr = FPGA_ADDR_PWR_TYPE_ACT;
            break;

        case FUNCINF_PWR_TYPE_REACT:
            addr = FPGA_ADDR_PWR_TYPE_REACT;
            break;

        case FUNCINF_PWR_TYPE_BUS:
        case FUNCINF_PWR_TYPE_DC:
            addr = FPGA_ADDR_PWR_TYPE_DC;
            break;

        case FUNCINF_PWR_TYPE_BAT:
            addr = FPGA_ADDR_PWR_TYPE_BAT;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", pwrType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取功率因数
 */
funcInfErr_t FuncInf_GetPowerFactor(void *pParam, float *pValue)
{
    funcInfErr_t err;
    float actPwr, apparentPwr;

    if((err = FuncInf_GetPower(FUNCINF_PWR_TYPE_ACT, &actPwr)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if((err = FuncInf_GetPower(FUNCINF_PWR_TYPE_APPARENT, &apparentPwr)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    *pValue = actPwr / apparentPwr;

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取频率
 */
funcInfErr_t FuncInf_GetFrequency(void *pParam, float *pValue)
{
    uint16_t addr, fpgaVal;

    addr = FPGA_ADDR_FREQ;

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取限制
 */
funcInfErr_t FuncInf_GetLimit(funcInfLmtType_t lmtType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(lmtType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_LMT_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", lmtType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(lmtType)
    {
        case FUNCINF_LMT_TYPE_AC_CUR:
            addr = FPGA_ADDR_LMT_TYPE_AC_CUR;
            break;

        case FUNCINF_LMT_TYPE_AC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_AC_PWR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_AC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_AC_PWR_DISC;
            break;

        case FUNCINF_LMT_TYPE_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC_CUR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC_CUR_DISC;
            break;

        case FUNCINF_LMT_TYPE_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC_PWR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC_PWR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_CUR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_CUR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_PWR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_PWR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_CUR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_CUR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_PWR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_PWR_DISC;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", lmtType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取系统状态寄存器
 */
funcInfErr_t FuncInf_GetStateRegister(funcInfRegIdx_t regIdx, uint16_t *pValue)
{
    uint16_t addr, fpgaVal;

    switch(regIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_REG_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", regIdx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = FPGA_ADDR_STATE_REG_BEGIN + regIdx;

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }
    *pValue = fpgaVal;

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取系统故障寄存器
 */
funcInfErr_t FuncInf_GetFaultRegister(funcInfRegIdx_t regIdx, uint16_t *pValue)
{
    uint16_t addr, fpgaVal;

    switch(regIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_REG_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", regIdx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = FPGA_ADDR_FAULT_REG_BEGIN + regIdx; 

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }
    *pValue = fpgaVal;

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取输入寄存器
 */
funcInfErr_t FuncInf_GetInputRegister(void *pParam, uint16_t *pValue)
{
    return FuncInf_GetStateRegister(FUNCINF_REG_IDX_9, pValue);
}


/**
 * @brief 获取输出寄存器
 */
funcInfErr_t FuncInf_GetOutputRegister(void *pParam, uint16_t *pValue)
{
    return FuncInf_GetStateRegister(FUNCINF_REG_IDX_11, pValue);
}


/**
 * @brief 获取FPGA状态机
 */
funcInfErr_t FuncInf_GetFsm(funcInfFsmType_t fsmType, fpagDataFsm_t *pValue)
{
    funcInfErr_t err;
    uint16_t fsmReg;

    switch(fsmType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_FSM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", fsmType);
            return -FUNCINF_ERR_PARAM;
    }

    if((err = FuncInf_GetStateRegister(FUNCINF_REG_IDX_8, &fsmReg)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    switch(fsmType)
    {
        case FUNCINF_FSM_TYPE_THIS_TIME:
            *pValue = (fsmReg & 0xF);
            break;

        case FUNCINF_FSM_TYPE_1_LAST_TIME:
            *pValue = ((fsmReg >> 4) & 0xF);
            break;

        case FUNCINF_FSM_TYPE_2_LAST_TIME:
            *pValue = ((fsmReg >> 8) & 0xF);
            break;

        case FUNCINF_FSM_TYPE_3_LAST_TIME:
            *pValue = ((fsmReg >> 12) & 0xF);
            break;

        default:
            PRINT_WARN("Parameter error[%d]", fsmType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(*pValue)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_FSM_TABLE
    #undef X_MACRO
            return FUNCINF_ERR_NONE;
    
        default:
            PRINT_WARN("Out of enumeration[%d]", *pValue);
            return -FUNCINF_ERR_ENUM;
    }
}


/**
 * @brief 获取命令值
 */
funcInfErr_t FuncInf_GetCmd(funcInfCmdIdx_t cmdIdx, uint16_t *pValue)
{
    uint16_t addr, fpgaVal;

    switch(cmdIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CMD_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", cmdIdx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = FPGA_ADDR_CMD_BEGIN + cmdIdx;

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }
    *pValue = fpgaVal;


    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取运行模式
 */
funcInfErr_t FuncInf_GetRunMode(void *pParam, funcInfRunMode_t *pValue)
{
    funcInfErr_t err;
    u16BitType_t cmd1, cmd2;
    uint16_t viMode;

    ((void)(viMode));

    if((err = FuncInf_GetCmd(FUNCINF_CMD_IDX_1, &cmd1.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if((err = FuncInf_GetCmd(FUNCINF_CMD_IDX_2, &cmd2.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if(cmd1.bitData.b5 == 0 && cmd1.bitData.b6 == 0 && cmd1.bitData.b7 == 0)
    {
        if(cmd2.bitData.b2 == 0)
        {
            *pValue = FUNCINF_RUN_MODE_VF;
        }
        else
        {
            *pValue = FUNCINF_RUN_MODE_VSG;
        }
    }
    else if(cmd1.bitData.b5 == 0 && cmd1.bitData.b6 == 0 && cmd1.bitData.b7 == 1)
    {
        if(cmd2.bitData.b2 == 0)
        {
            *pValue = FUNCINF_RUN_MODE_PQ;
        }
        else
        {
            *pValue = FUNCINF_RUN_MODE_VSG;
        }
    }
    else if(cmd1.bitData.b5 == 0 && cmd1.bitData.b6 == 1 && cmd1.bitData.b7 == 0)
    {
    #if 1
        *pValue = FUNCINF_RUN_MODE_VI;
    #else
        //MicroFile_3_Read(MF3_DATA_ADDR_VI_RUNMODE, &comData);
        //viMode = comData.cd_dataValue.uint16Value;
        if(viMode == 0)
        {
            *pValue = FUNCINF_RUN_MODE_CP;
        }
        else if(viMode == 1)
        {
            *pValue = FUNCINF_RUN_MODE_CC;
        }
        else if(viMode == 2)
        {
            *pValue = FUNCINF_RUN_MODE_CV;
        }
        else
        {
            *pValue = 0;
        }
    #endif
    }
    else if(1==cmd1.bitData.b5)
    {
        *pValue = FUNCINF_RUN_MODE_OL;
    }
    else
    {
	    *pValue = 0;
    }

    switch(*pValue)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_RUN_MODE_TABLE
    #undef X_MACRO
            return FUNCINF_ERR_NONE;
    
        default:
            PRINT_WARN("Out of enumeration[%d]", *pValue);
            return -FUNCINF_ERR_ENUM;
    }
}


/**
 * @brief 获取设备状态
 */
funcInfErr_t FuncInf_GetDevState(void *pParam, funcInfDevState_t *pValue)
{
    funcInfErr_t err;
    fpagDataFsm_t fsm;
    float actPwrCur;

    if((err = FuncInf_GetFsm(FUNCINF_FSM_TYPE_THIS_TIME, &fsm)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if (fsm == FUNCINF_FSM_IDLE)
    {
        *pValue = FUNCINF_DEV_STATE_SHUTDOWN;
    }
    else if (fsm == FUNCINF_FSM_WORKING)
    {
        if((err = FuncInf_GetPower(FUNCINF_PWR_TYPE_ACT, &actPwrCur)) != FUNCINF_ERR_NONE)
        {
            return err;
        }

        if (actPwrCur > 3.0F)
        {
            *pValue = FUNCINF_DEV_STATE_DISCING;
        }
        else if (actPwrCur < -3.0F)
        {
            *pValue = FUNCINF_DEV_STATE_CHRGING;
        }
        else
        {
            *pValue = FUNCINF_DEV_STATE_STANDBY;
        }
    }
    else if (fsm == FUNCINF_FSM_FAULT)
    {
        *pValue = FUNCINF_DEV_STATE_FAULT;
    }
    else
    {
        *pValue = FUNCINF_DEV_STATE_SHUTDOWN;
    }

    switch(*pValue)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_DEV_STATE_TABLE
    #undef X_MACRO
            return FUNCINF_ERR_NONE;
    
        default:
            PRINT_WARN("Out of enumeration[%d]", *pValue);
            return -FUNCINF_ERR_ENUM;
    }
}


/**
 * @brief 获取并离网状态
 */
funcInfErr_t FuncInf_GetGridState(void *pParam, funcInfGridState_t *pValue)
{
    funcInfErr_t err;
    funcInfRunMode_t runMode;
    u16BitType_t state;

    if((err = FuncInf_GetRunMode(NULL, &runMode)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    switch(runMode)
    {
        case FUNCINF_RUN_MODE_PQ:
        case FUNCINF_RUN_MODE_VI:
        case FUNCINF_RUN_MODE_CV:
        case FUNCINF_RUN_MODE_CC:
        case FUNCINF_RUN_MODE_CP:
            *pValue = FUNCINF_GRID_STATE_ON;
            break;
            
        case FUNCINF_RUN_MODE_VF:
            *pValue = FUNCINF_GRID_STATE_OFF;
            break;
            
        case FUNCINF_RUN_MODE_VSG:
            if((err = FuncInf_GetStateRegister(FUNCINF_REG_IDX_10, &state.u16Data)) != FUNCINF_ERR_NONE)
            {
                return err;
            }
            *pValue = state.bitData.b14 == 0 ? FUNCINF_GRID_STATE_OFF : FUNCINF_GRID_STATE_ON;
            break;
        
        default:
            PRINT_WARN("Parameter error[%d]", runMode);
            return -FUNCINF_ERR_PARAM;
    }

    switch(*pValue)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_GRID_STATE_TABLE
    #undef X_MACRO
            return FUNCINF_ERR_NONE;
    
        default:
            PRINT_WARN("Out of enumeration[%d]", *pValue);
            return -FUNCINF_ERR_ENUM;
    }
}


/**
 * @brief 获取保护阈值
 */
funcInfErr_t FuncInf_GetProtectThreshold(funcInfThrshdType_t thrshdType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(thrshdType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_THRSHD_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", thrshdType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(thrshdType)
    {
        case FUNCINF_THRSHD_TYPE_L1_AC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_OV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_OV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_UV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_UV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_OV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_OV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_UV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_UV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_OF:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_OF;
            break;

        case FUNCINF_THRSHD_TYPE_L1_UF:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_UF;
            break;

        case FUNCINF_THRSHD_TYPE_L1_OF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_OF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_UF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_UF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_OF:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_OF;
            break;

        case FUNCINF_THRSHD_TYPE_L2_UF:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_UF;
            break;

        case FUNCINF_THRSHD_TYPE_L2_OF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_OF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_UF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_UF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OC;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_DC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OC;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OV;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_UV;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OC;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BUS_VOL_DIFF:
            addr = FPGA_ADDR_THRSHD_TYPE_BUS_VOL_DIFF;
            break;

        case FUNCINF_THRSHD_TYPE_CUR_ZERO_BACK:
            addr = FPGA_ADDR_THRSHD_TYPE_CUR_ZERO_BACK;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", thrshdType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取给定值
 */
funcInfErr_t FuncInf_GetAppointValue(funcInfAppointType_t appointType, float *pValue)
{
    uint16_t addr, fpgaVal;

    switch(appointType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_APPOINT_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", appointType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(appointType)
    {
        case FUNCINF_APPOINT_TYPE_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_AC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_AC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_ACT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_ACT_PWR;
            break;

        case FUNCINF_APPOINT_TYPE_REACT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_REACT_PWR;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_CUR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_CUR;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_PWR;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_CUR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_CUR;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_PWR;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", appointType);
            return -FUNCINF_ERR_PARAM;
    }

    if(FpgaInf_Read(addr, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    if(RatioCoef_GetRealValue(addr, fpgaVal, pValue) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }
    
    return FUNCINF_ERR_NONE;
}
#endif


#if 1
/**
 * @brief 直写FPGA
 */
funcInfErr_t FuncInf_DirectWriteFpga(funcInfOperator_t cmder, uint32_t addr, uint16_t value)
{
    u16BitType_t cmd;
    uint16_t i;

    if(addr >= FPGA_ADDR_MAX / 2)
    {
        PRINT_WARN("Parameter error[%d]", addr);
        return -FUNCINF_ERR_PARAM;
    }

    cmd.u16Data = value;

    switch(addr)
    {
        case FPGA_ADDR_CMD_BEGIN + 0:
            if(cmd.bitData.b0 == 1)
            {
                if(FuncInf_IsForbidTurnOn() != 0)
                {
                    return FUNCINF_ERR_NONE;
                }
            }
            else if(cmd.bitData.b1 == 1)
            {
                if(FuncInf_ClearAppointPwr() != 0)
                {
                    return FUNCINF_ERR_NONE;
                }
                for(i = 0; i < 3; i++)
                {
                    TableRefresh_SetArmFaultState(i, 0);
                    FuncInf_DirectWriteFpga(FUNCINF_OPERATOR_UPPER, FPGA_ADDR_ARM_FAULT_REG_BEGIN + i, 0);
                }
            }
            else if(cmd.bitData.b3 == 1)
            {
                FuncInf_SetupZeroCalibration();
            }
            else if(cmd.bitData.b4 == 1)
            {
                FuncInf_CancelZeroCalibration();
            }
            break;
    }

    if(FpgaInf_Write(addr, value) != 0)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    if(ParamTable_Set(addr, value) != TABLE_ERR_NONE)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    switch(addr)
    {
        case FPGA_ADDR_APPOINT_TYPE_ACT_PWR:
        case FPGA_ADDR_APPOINT_TYPE_REACT_PWR:
        case FPGA_ADDR_LMT_TYPE_AC_PWR_CHRG:
        case FPGA_ADDR_LMT_TYPE_AC_PWR_DISC:
            PulseOperate_SendMessage();
            break;
        
        case FPGA_ADDR_CMD_BEGIN + 1:
        case FPGA_ADDR_CMD_BEGIN + 2:
            TableRefresh_SendMessage(TABLE_MSGVAL_MODE);
            PulseOperate_SendMessage();
            break;
    }

    switch(addr)
    {
        /* 不记录日志 */
        case FPGA_ADDR_220:
        case FPGA_ADDR_221:
        case FPGA_ADDR_222:
            return FUNCINF_ERR_NONE;
    }

    if(addr == FPGA_ADDR_CMD_BEGIN + 0 && \
       cmder == FUNCINF_OPERATOR_UPPER)
    {
        if(cmd.bitData.b0  == 1)
        {
            GlobalVariable_SetUint16(GV_UINT16_PREVONOFFCOMMANDER, 8);
            logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 450 + 1, COM_DATA_TYPE_NONE, NULL);
            syslog(LOG_INFO, "%s: %s FUNCINF_TURN_ON", __func__, strCmder[cmder]);
        }
        if(cmd.bitData.b1  == 1)
        {
            GlobalVariable_SetUint16(GV_UINT16_PREVONOFFCOMMANDER, 4);
            logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 450 + 0, COM_DATA_TYPE_NONE, NULL);
            syslog(LOG_INFO, "%s: %s FUNCINF_TURN_OFF", __func__, strCmder[cmder]);
        }
    }

    if(cmder != FUNCINF_OPERATOR_1547)
    {
        // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, addr, COM_DATA_TYPE_NONE, NULL);
        syslog(LOG_INFO, "%s: %s %d %d", __func__, strCmder[cmder], addr, (int16_t)value);
    }

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设定限制
 */
funcInfErr_t FuncInf_SetLimit(funcInfOperator_t cmder, funcInfLmtType_t lmtType, float value)
{
    uint16_t addr, fpgaVal;

    switch(lmtType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_LMT_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", lmtType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(lmtType)
    {
        case FUNCINF_LMT_TYPE_AC_CUR:
            addr = FPGA_ADDR_LMT_TYPE_AC_CUR;
            break;

        case FUNCINF_LMT_TYPE_AC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_AC_PWR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_AC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_AC_PWR_DISC;
            break;

        case FUNCINF_LMT_TYPE_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC_CUR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC_CUR_DISC;
            break;

        case FUNCINF_LMT_TYPE_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC_PWR_CHRG;
            break;

        case FUNCINF_LMT_TYPE_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC_PWR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_CUR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_CUR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_PWR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC1_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC1_DC_PWR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_CUR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_CUR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_CUR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_CUR_DISC;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_PWR_CHRG:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_PWR_CHRG;
            break;

        case  FUNCINF_LMT_TYPE_DC2_DC_PWR_DISC:
            addr = FPGA_ADDR_LMT_TYPE_DC2_DC_PWR_DISC;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", lmtType);
            return -FUNCINF_ERR_PARAM;
    }

    if(RatioCoef_GetFpgaValue(addr, value, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    if(FuncInf_DirectWriteFpga(cmder, addr, fpgaVal) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    if(cmder != FUNCINF_OPERATOR_INIT)
    {
        // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 300 + lmtType, COM_DATA_TYPE_NONE, NULL);
    }
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strLmtType[lmtType], (int16_t)value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设定命令值
 */
funcInfErr_t FuncInf_SetCmd(funcInfOperator_t cmder, funcInfCmdIdx_t cmdIdx, uint16_t value)
{
    uint16_t addr;

    switch(cmdIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CMD_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", cmdIdx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = FPGA_ADDR_CMD_BEGIN + cmdIdx;

    if(FuncInf_DirectWriteFpga(cmder, addr, value) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 320 + cmdIdx, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s 0x%04X", __func__, strCmder[cmder], strCmdIdx[cmdIdx], value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 置位命令位
 */
funcInfErr_t FuncInf_SetCmdBit(funcInfOperator_t cmder, funcInfCmdIdx_t cmdIdx, funcInfBitIdx_t bitIdx)
{
    funcInfErr_t err;
    u16BitType_t cmd;

    switch(cmdIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CMD_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", cmdIdx);
            return -FUNCINF_ERR_PARAM;
    }

    switch(bitIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_BIT_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", bitIdx);
            return -FUNCINF_ERR_PARAM;
    }

    if((err = FuncInf_GetCmd(cmdIdx, &cmd.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if(((cmd.u16Data >> bitIdx) & 0x1) == 0)
    {
        cmd.u16Data |= (1 << bitIdx);
    }

    if((err = FuncInf_SetCmd(cmder, cmdIdx, cmd.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 330 + bitIdx, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %s", __func__, strCmder[cmder], strCmdIdx[cmdIdx], strBitIdx[bitIdx]);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 清除命令位
 */
funcInfErr_t FuncInf_ClearCmdBit(funcInfOperator_t cmder, funcInfCmdIdx_t cmdIdx, funcInfBitIdx_t bitIdx)
{
    funcInfErr_t err;
    u16BitType_t cmd;

    switch(cmdIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CMD_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", cmdIdx);
            return -FUNCINF_ERR_PARAM;
    }

    switch(bitIdx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_BIT_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", bitIdx);
            return -FUNCINF_ERR_PARAM;
    }

    if((err = FuncInf_GetCmd(cmdIdx, &cmd.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if(((cmd.u16Data >> bitIdx) & 0x1) == 1)
    {
        cmd.u16Data &= ~(1 << bitIdx);
    }

    if((err = FuncInf_SetCmd(cmder, cmdIdx, cmd.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 350 + bitIdx, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %s", __func__, strCmder[cmder], strCmdIdx[cmdIdx], strBitIdx[bitIdx]);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设定运行模式
 */
funcInfErr_t FuncInf_SetRunMode(funcInfOperator_t cmder, void *pParam, funcInfRunMode_t value)
{
    funcInfErr_t err;
    u16BitType_t mode, cmd1, cmd2;
    uint16_t viMode, idxLog, addr = 710;

    ((void)(viMode));

    switch(value)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_RUN_MODE_TABLE
    #undef X_MACRO
            break;
        
        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    if((err = FuncInf_GetMode(NULL, &mode.u16Data)) != FUNCINF_ERR_NONE)
    {
        return err;
    }

    if(FuncInf_GetCmd(FUNCINF_CMD_IDX_1, &cmd1.u16Data) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Get failure");
        return -FUNCINF_ERR_READ;
    }
    if(FuncInf_GetCmd(FUNCINF_CMD_IDX_2, &cmd2.u16Data) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Get failure");
        return -FUNCINF_ERR_READ;
    }

    switch(value)
    {
        case FUNCINF_RUN_MODE_PQ:
            mode.bitData.b8 = 1;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 0;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 0;
            cmd1.bitData.b7 = 1;
            cmd2.bitData.b2 = 0;
            break;

        case FUNCINF_RUN_MODE_VF:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 1;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 1;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 0;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;

        case FUNCINF_RUN_MODE_VSG:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 1;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 2;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 0;
            cmd1.bitData.b7 = 0;
            cmd2.bitData.b2 = 1;
            break;

        case FUNCINF_RUN_MODE_VI:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 1;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 3;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 1;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;
        
        case FUNCINF_RUN_MODE_CV:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 1;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 4;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 1;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;

        case FUNCINF_RUN_MODE_CC:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 1;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            idxLog = 5;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 1;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;

        case FUNCINF_RUN_MODE_CP:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 1;
            mode.bitData.b15 = 0;
            idxLog = 6;
            cmd1.bitData.b5 = 0;
            cmd1.bitData.b6 = 1;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;

        case FUNCINF_RUN_MODE_OL:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 1;
            idxLog = 7;
            cmd1.bitData.b5 = 1;
            cmd1.bitData.b6 = 0;
            cmd1.bitData.b7 = 0;
            cmd1.bitData.b8 = 0;
            cmd2.bitData.b2 = 0;
            break;
        
        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    if(FuncInf_SetCmd(cmder, FUNCINF_CMD_IDX_1, cmd1.u16Data) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Set failure");
        return -FUNCINF_ERR_WRITE;
    }
    if(FuncInf_SetCmd(cmder, FUNCINF_CMD_IDX_2, cmd2.u16Data) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Set failure");
        return -FUNCINF_ERR_WRITE;
    }

    UpperTable_Write(addr, mode.u16Data);
    ParamTable_Set(addr, mode.u16Data);
    TableRefresh_SendMessage(TABLE_MSGVAL_MODE);
    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 370 + idxLog, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s 0x%04X", __func__, strCmder[cmder], value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设定保护阈值
 */
funcInfErr_t FuncInf_SetProtectThreshold(funcInfOperator_t cmder, funcInfThrshdType_t thrshdType, float value)
{
    uint16_t addr, fpgaVal;

    switch(thrshdType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_THRSHD_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", thrshdType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(thrshdType)
    {
        case FUNCINF_THRSHD_TYPE_L1_AC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_OV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_OV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_AC_UV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_AC_UV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_OV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_OV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_AC_UV_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_AC_UV_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_OF:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_OF;
            break;

        case FUNCINF_THRSHD_TYPE_L1_UF:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_UF;
            break;

        case FUNCINF_THRSHD_TYPE_L1_OF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_OF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L1_UF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L1_UF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_OF:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_OF;
            break;

        case FUNCINF_THRSHD_TYPE_L2_UF:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_UF;
            break;

        case FUNCINF_THRSHD_TYPE_L2_OF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_OF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_L2_UF_TIME:
            addr = FPGA_ADDR_THRSHD_TYPE_L2_UF_TIME;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OC;
            break;

        case FUNCINF_THRSHD_TYPE_AC_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_AC_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OV;
            break;

        case FUNCINF_THRSHD_TYPE_DC_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_UV;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OC;
            break;

        case FUNCINF_THRSHD_TYPE_DC_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_DC_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OV:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OV;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_UV:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_UV;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OV_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OV_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OC:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OC;
            break;

        case FUNCINF_THRSHD_TYPE_BAT_OC_INST:
            addr = FPGA_ADDR_THRSHD_TYPE_BAT_OC_INST;
            break;

        case FUNCINF_THRSHD_TYPE_BUS_VOL_DIFF:
            addr = FPGA_ADDR_THRSHD_TYPE_BUS_VOL_DIFF;
            break;

        case FUNCINF_THRSHD_TYPE_CUR_ZERO_BACK:
            addr = FPGA_ADDR_THRSHD_TYPE_CUR_ZERO_BACK;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", thrshdType);
            return -FUNCINF_ERR_PARAM;
    }

    if(RatioCoef_GetFpgaValue(addr, value, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    if(FuncInf_DirectWriteFpga(cmder, addr, fpgaVal) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 380 + thrshdType, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strThrshdType[thrshdType], (int16_t)value);
        
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设定给定值
 */
funcInfErr_t FuncInf_SetAppointValue(funcInfOperator_t cmder, funcInfAppointType_t appointType, float value)
{
    uint16_t addr, fpgaVal;

    switch(appointType)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_APPOINT_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", appointType);
            return -FUNCINF_ERR_PARAM;
    }

    switch(appointType)
    {
        case FUNCINF_APPOINT_TYPE_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_AC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_AC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_ACT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_ACT_PWR;
            if(Ieee1547_GetModeSwitch(MODE_FP) == MODE_SWITCH_ON)
            {
                Ieee1547_ModeFP_SetActPwr((int16_t)(value * 10));
                return FUNCINF_ERR_NONE;
            }
            if(Ieee1547_GetModeSwitch(MODE_VP) == MODE_SWITCH_ON)
            {
                Ieee1547_ModeVP_SetAbsorbActPwr((int16_t)(value * 10));
                return FUNCINF_ERR_NONE;
            }
            if(Ieee1547_GetModeSwitch(MODE_CPF) == MODE_SWITCH_ON)
            {
                Ieee1547_ModeCPF_SetActPwr((int16_t)(value * 10));
            }
            break;

        case FUNCINF_APPOINT_TYPE_REACT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_REACT_PWR;
            if(Ieee1547_GetModeSwitch(MODE_CQ) == MODE_SWITCH_ON)
            {
                Ieee1547_ModeCQ_SetReactPwr((int16_t)(value * 10));
            }
            break;

        case FUNCINF_APPOINT_TYPE_DC1_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_CUR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_CUR;
            break;

        case FUNCINF_APPOINT_TYPE_DC1_BAT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC1_BAT_PWR;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_DC_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_DC_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_VOL:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_VOL;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_CUR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_CUR;
            break;

        case FUNCINF_APPOINT_TYPE_DC2_BAT_PWR:
            addr = FPGA_ADDR_APPOINT_TYPE_DC2_BAT_PWR;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", appointType);
            return -FUNCINF_ERR_PARAM;
    }

    if(RatioCoef_GetFpgaValue(addr, value, &fpgaVal) != 0)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_CONVERT;
    }

    if(FuncInf_DirectWriteFpga(cmder, addr, fpgaVal) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Write failure");
        return -FUNCINF_ERR_WRITE;
    }

    if(cmder != FUNCINF_OPERATOR_1547 && \
       cmder != FUNCINF_OPERATOR_TIME_PERIOD)
    {
        // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 420 + appointType, COM_DATA_TYPE_NONE, NULL);
        syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strAppointType[appointType], (int16_t)value);
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 控制ARM故障灯
 */
funcInfErr_t FuncInf_CtrlArmFaultLamp(funcInfOperator_t cmder, void *pParam, funcInfLamp_t value)
{
    funcInfErr_t err;

    switch(value)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_LAMP_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    switch(value)
    {
        case FUNCINF_LAMP_OFF:
            if((err = FuncInf_ClearCmdBit(cmder, FUNCINF_CMD_IDX_3, FUNCINF_BIT_IDX_2)) != FUNCINF_ERR_NONE)
            {
                return err;
            }
            break;
            
        case FUNCINF_LAMP_ON:
            if((err = FuncInf_SetCmdBit(cmder, FUNCINF_CMD_IDX_3, FUNCINF_BIT_IDX_2)) != FUNCINF_ERR_NONE)
            {
                return err;
            }
            break;
        
        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 440 + value, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s", __func__, strCmder[cmder], strLamp[value]);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 开关机
 */
funcInfErr_t FuncInf_TurnOnOff(funcInfOperator_t cmder, void *pParam, funcInfTurn_t value)
{
    funcInfErr_t err;
    uint16_t swRecord = 0, i;

    switch(value)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_TURN_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    switch(value)
    {
        case FUNCINF_TURN_OFF:
            if(FuncInf_SetAppointValue(cmder, FUNCINF_APPOINT_TYPE_ACT_PWR, 0) != FUNCINF_ERR_NONE)
            {
                PRINT_WARN();
                return -1;
            }
            if(FuncInf_SetAppointValue(cmder, FUNCINF_APPOINT_TYPE_REACT_PWR, 0) != FUNCINF_ERR_NONE)
            {
                PRINT_WARN();
                return -1;
            }
            for(i = 0; i < 3; i++)
            {
                TableRefresh_SetArmFaultState(i, 0);
                FuncInf_DirectWriteFpga(FUNCINF_OPERATOR_UPPER, FPGA_ADDR_ARM_FAULT_REG_BEGIN + i, 0);
            }
            if((err = FuncInf_SetCmdBit(cmder, FUNCINF_CMD_IDX_0, FUNCINF_BIT_IDX_1)) != FUNCINF_ERR_NONE)
            {
                return err;
            }
            break;
            
        case FUNCINF_TURN_ON:
            if(FuncInf_IsForbidTurnOn() != 0)
            {
                return -1;
            }
            if((err = FuncInf_SetCmdBit(cmder, FUNCINF_CMD_IDX_0, FUNCINF_BIT_IDX_0)) != FUNCINF_ERR_NONE)
            {
                return err;
            }
            break;
        
        default:
            PRINT_WARN("Parameter error[%d]", value);
            return -FUNCINF_ERR_PARAM;
    }

    GlobalVariable_GetUint16(GV_UINT16_PREVONOFFCOMMANDER, &swRecord);
    if(value == FUNCINF_TURN_OFF)
    {
        switch(cmder)
        {
            case FUNCINF_OPERATOR_UPPER:
                swRecord = 4;
                break;

            case FUNCINF_OPERATOR_HMI:
                swRecord = 16;
                break;

            case FUNCINF_OPERATOR_EMS:
                swRecord = 64;
                break;

            case FUNCINF_OPERATOR_BMS:
                swRecord = 256;
                break;

            case FUNCINF_OPERATOR_LC:
                swRecord = 1024;
                break;

            default:
                break;
        }
    }
    else if(value == FUNCINF_TURN_ON)
    {
        switch(cmder)
        {
            case FUNCINF_OPERATOR_UPPER:
                swRecord = 8;
                break;

            case FUNCINF_OPERATOR_HMI:
                swRecord = 32;
                break;

            case FUNCINF_OPERATOR_EMS:
                swRecord = 128;
                break;

            case FUNCINF_OPERATOR_BMS:
                swRecord = 512;
                break;

            case FUNCINF_OPERATOR_LC:
                swRecord = 2048;
                break;

            default:
                break;
        }
    }
    GlobalVariable_SetUint16(GV_UINT16_PREVONOFFCOMMANDER, swRecord);

    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 450 + value, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s", __func__, strCmder[cmder], strTurn[value]);

    return FUNCINF_ERR_NONE;
}
#endif


#if 1
/**
 * @brief 获取IGBT温度
 */
funcInfErr_t FuncInf_GetIgbtTemperature(funcInfIgbtTempType_t type, float *pValue)
{
    int16_t temp = 0;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_IGBT_TEMP_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_IGBT_TEMP_TYPE_A0:
            if(TempSample_GetTemperature(TS_AREA_PHASE_A0, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_A1:
            if(TempSample_GetTemperature(TS_AREA_PHASE_A1, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_B0:
            if(TempSample_GetTemperature(TS_AREA_PHASE_B0, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_B1:
            if(TempSample_GetTemperature(TS_AREA_PHASE_B1, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_C0:
            if(TempSample_GetTemperature(TS_AREA_PHASE_C0, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_C1:
            if(TempSample_GetTemperature(TS_AREA_PHASE_C1, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AL23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_A0, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AL14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_A0, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AR23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_A1, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AR14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_A1, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BL23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_B0, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BL14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_B0, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BR23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_B1, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BR14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_B1, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CL23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_C0, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CL14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_C0, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CR23:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_C1, TS_POINT_23, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CR14:
            if(TempSample_GetSamplePointTemperature(TS_AREA_PHASE_C1, TS_POINT_14, &temp) != 0)
            {
                PRINT_WARN("Get temperature failure");
            }
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    *pValue = (float)temp;
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取IGBT温度AD值
 */
funcInfErr_t FuncInf_GetIgbtTemperatureAd(funcInfIgbtTempType_t type, uint16_t *pValue)
{
    uint16_t adValue;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_IGBT_TEMP_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_IGBT_TEMP_TYPE_A0:
        case FUNCINF_IGBT_TEMP_TYPE_A1:
        case FUNCINF_IGBT_TEMP_TYPE_B0:
        case FUNCINF_IGBT_TEMP_TYPE_B1:
        case FUNCINF_IGBT_TEMP_TYPE_C0:
        case FUNCINF_IGBT_TEMP_TYPE_C1:
            adValue = 0;
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AL23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_A0, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AL14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_A0, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AR23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_A1, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_AR14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_A1, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BL23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_B0, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BL14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_B0, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BR23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_B1, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_BR14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_B1, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CL23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_C0, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CL14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_C0, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CR23:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_C1, TS_POINT_23, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        case FUNCINF_IGBT_TEMP_TYPE_CR14:
            if(TempSample_GetSamplePointAdValue(TS_AREA_PHASE_C1, TS_POINT_14, &adValue) != 0)
            {
                PRINT_WARN("Get ad value failure");
            }
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    *pValue = adValue;
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取电量
 */
funcInfErr_t FuncInf_GetElectricQuantity(funcInfElecQuttType_t type, float *pValue)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_ELEC_QUTT_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_ELEC_QUTT_TYPE_AC_DISC_DAY:
            *pValue = eqsQuttDataTodayGet(IS_DISC, BRANCH_TYPE_AC);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_AC_CHRG_DAY:
            *pValue = eqsQuttDataTodayGet(IS_CHRG, BRANCH_TYPE_AC);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_AC_DISC_TOT:
            *pValue = eqsQuttDataTotalGet(IS_DISC, BRANCH_TYPE_AC);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_AC_CHRG_TOT:
            *pValue = eqsQuttDataTotalGet(IS_CHRG, BRANCH_TYPE_AC);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_DC_DISC_DAY:
            *pValue = eqsQuttDataTodayGet(IS_DISC, BRANCH_TYPE_BAT);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_DC_CHRG_DAY:
            *pValue = eqsQuttDataTodayGet(IS_CHRG, BRANCH_TYPE_BAT);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_DC_DISC_TOT:
            *pValue = eqsQuttDataTotalGet(IS_DISC, BRANCH_TYPE_BAT);
            break;
            
        case FUNCINF_ELEC_QUTT_TYPE_DC_CHRG_TOT:
            *pValue = eqsQuttDataTotalGet(IS_CHRG, BRANCH_TYPE_BAT);
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取版本
 */
funcInfErr_t FuncInf_GetVersion(funcInfVerType_t type, uint16_t *pValue)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_VER_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_VER_TYPE_V:
            *pValue = ARM_VERSION_V;
            break;

        case FUNCINF_VER_TYPE_C:
            *pValue = ARM_VERSION_C;
            break;
            
        case FUNCINF_VER_TYPE_B:
            *pValue = ARM_VERSION_B;
            break;
            
        case FUNCINF_VER_TYPE_R:
            *pValue = ARM_VERSION_R;
            break;
            
        case FUNCINF_VER_TYPE_ALL:
            *pValue = ARM_VERSION;
            break;
    
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取变比系数
 */
funcInfErr_t FuncInf_GetRatioCoef(funcInfRatioCoefType_t type, float *pValue)
{
    uint16_t addr, rcH, rcL;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_RATIO_COEF_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_RATIO_COEF_TYPE_NULL:
            *pValue = 1.0F;
            return FUNCINF_ERR_NONE;

        case FUNCINF_RATIO_COEF_TYPE_AC_VOL:
            addr = 600;
            break;

        case FUNCINF_RATIO_COEF_TYPE_AC_CUR:
            addr = 602;
            break;

        case FUNCINF_RATIO_COEF_TYPE_AC_PWR:
            addr = 604;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_VOL:
            addr = 606;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_CUR:
            addr = 608;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_PWR:
            addr = 610;
            break;

        case FUNCINF_RATIO_COEF_TYPE_BAT_VOL:
            addr = 612;
            break;

        case FUNCINF_RATIO_COEF_TYPE_POS_VOL:
            addr = 614;
            break;

        case FUNCINF_RATIO_COEF_TYPE_NEG_VOL:
            addr = 616;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    ParamTable_Get(addr, &rcL);
    ParamTable_Get(addr + 1, &rcH);
    *pValue = (float)((rcH << 16) | rcL) / 100000.0F;
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取网络参数
 */
funcInfErr_t FuncInf_GetNetParam(funcInfNetParamType_t type, uint16_t *pValue)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_NET_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    if(NetParam_Get((netParamType_t)type, pValue) != 0)
    {
        PRINT_WARN("Get failure");
        return -FUNCINF_ERR_READ;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取HMI从机地址
 */
funcInfErr_t FuncInf_GetHmiSlaveId(void *pParam, uint16_t *pValue)
{   
    uint16_t addr = 690;

    ParamTable_Get(addr, pValue);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取最值
 */
funcInfErr_t FuncInf_GetExtremeValue(funcInfExtrValType_t type, float *pValue)
{
    uint16_t addr;
    uint16_t extr;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_EXTR_VAL_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 700 + type;
    ParamTable_Get(addr, &extr);
    *pValue = (float)(int16_t)extr;

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取控制模式
 */
funcInfErr_t FuncInf_GetCtrlMode(void *pParam, funcInfCtrlMode_t *pValue)
{
    uint16_t addr = 710;
    u16BitType_t mode;
   
    ParamTable_Get(addr, &mode.u16Data);

    if(mode.bitData.b0 == 1 && mode.bitData.b1 == 0)
    {
        *pValue = FUNCINF_CTRL_MODE_LOCAL;
        return FUNCINF_ERR_NONE;
    }
    else if(mode.bitData.b0 == 0 && mode.bitData.b1 == 1)
    {
        *pValue = FUNCINF_CTRL_MODE_REMOTE;
        return FUNCINF_ERR_NONE;
    }
    else
    {
        PRINT_WARN("Out of enumeration[%d]", *pValue);
        return -FUNCINF_ERR_ENUM;
    }
}


/**
 * @brief 获取模式
 */
funcInfErr_t FuncInf_GetMode(void *pParam, uint16_t *pValue)
{
    uint16_t addr = 710;
    u16BitType_t mode;
    funcInfRunMode_t runMode;

    ParamTable_Get(addr, &mode.u16Data);

    if(FuncInf_GetRunMode(NULL, &runMode) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Get failure");
        return -FUNCINF_ERR_READ;
    }

    switch(runMode)
    {
        case FUNCINF_RUN_MODE_PQ:
            mode.bitData.b8 = 1;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VF:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 1;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VSG:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 1;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VI:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 1;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;
        
        case FUNCINF_RUN_MODE_CV:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 1;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_CC:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 1;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_CP:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 1;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_OL:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 1;
            break;
        
        default:
            PRINT_WARN("Out of enumeration[%d]", runMode);
            return -FUNCINF_ERR_ENUM;
    }

    *pValue = mode.u16Data;
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取测试开关
 */
funcInfErr_t FuncInf_GetTestSwitch(funcInfTestSwitchType_t type, uint16_t *pValue)
{
    uint16_t addr = 712, test;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_TEST_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    ParamTable_Get(addr, &test);

    if(type == FUNCINF_TEST_SWITCH_TYPE_ALL)
    {
        *pValue = test;
    }
    else
    {
        *pValue = GET_BIT(test, type);
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取通讯开关
 */
funcInfErr_t FuncInf_GetCommunicateSwitch(funcInfCommSwitchType_t type, uint16_t *pValue)
{
    uint16_t addr = 714, comm;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_COMM_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    ParamTable_Get(addr, &comm);

    if(type == FUNCINF_COMM_SWITCH_TYPE_ALL)
    {
        *pValue = comm;
    }
    else
    {
        *pValue = GET_BIT(comm, type);
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取策略开关
 */
funcInfErr_t FuncInf_GetStrategySwitch(funcInfStrtgSwitchType_t type, uint16_t *pValue)
{
    uint16_t addr = 716, strtg;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_STRTG_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    ParamTable_Get(addr, &strtg);

    if(type == FUNCINF_STRTG_SWITCH_TYPE_ALL)
    {
        *pValue = strtg;
    }
    else
    {
        *pValue = GET_BIT(strtg, type);
    }
    
    return FUNCINF_ERR_NONE;
}

/**
 * @brief 获取ARM阈值
 */
funcInfErr_t FuncInf_GetArmThrshd(funcInfArmThrType_t type, float *pValue)
{
    uint16_t addr, thrshd;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_ARM_THR_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_ARM_THR_TYPE_3L_OV_THR:
        case FUNCINF_ARM_THR_TYPE_3L_UV_THR:
        case FUNCINF_ARM_THR_TYPE_3L_OF_THR:
        case FUNCINF_ARM_THR_TYPE_3L_UF_THR:
            addr = 770 + type;  
            ParamTable_Get(addr, &thrshd);
            *pValue = (float)(int16_t)thrshd;
            break;

        case FUNCINF_ARM_THR_TYPE_3L_OV_TIME:
        case FUNCINF_ARM_THR_TYPE_3L_UV_TIME:
            addr = 770 + type;  
            ParamTable_Get(addr, &thrshd);
            *pValue = (float)(int16_t)thrshd / 100;
            break;

        case FUNCINF_ARM_THR_TYPE_3L_OF_TIME:
        case FUNCINF_ARM_THR_TYPE_3L_UF_TIME:
            addr = 770 + type;  
            ParamTable_Get(addr, &thrshd);
            *pValue = (float)(int16_t)thrshd / 50;
            break;

        case FUNCINF_ARM_THR_TYPE_HIG_TEMP_DERATE:
        case FUNCINF_ARM_THR_TYPE_TEMP_DIFF:
        case FUNCINF_ARM_THR_TYPE_LEAK_CUR:
            addr = 720 + type - FUNCINF_ARM_THR_TYPE_HIG_TEMP_DERATE;  
            ParamTable_Get(addr, &thrshd);
            *pValue = (float)(int16_t)thrshd;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取功率爬坡率
 */
funcInfErr_t FuncInf_GetPwrSloped(void *pParam, float *pValue)
{    
    uint16_t addr = 730, slope;

    ParamTable_Get(addr, &slope);

    *pValue = (float)(int16_t)slope / 10;

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取时段参数
 */
funcInfErr_t FuncInf_GetPeriodParam(funcInfPeriodParamType_t type, float *pValue)
{
    uint16_t addr, param;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_PERIOD_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 740 + type;
    ParamTable_Get(addr, &param);

    switch(type)
    {
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_1:
        case FUNCINF_PERIOD_PARAM_TYPE_END_1:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_2:
        case FUNCINF_PERIOD_PARAM_TYPE_END_2:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_3:
        case FUNCINF_PERIOD_PARAM_TYPE_END_3:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_4:
        case FUNCINF_PERIOD_PARAM_TYPE_END_4:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_5:
        case FUNCINF_PERIOD_PARAM_TYPE_END_5:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_6:
        case FUNCINF_PERIOD_PARAM_TYPE_END_6:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_7:
        case FUNCINF_PERIOD_PARAM_TYPE_END_7:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_8:
        case FUNCINF_PERIOD_PARAM_TYPE_END_8:
            *pValue = (float)(int16_t)param / 100;
            break;

        case FUNCINF_PERIOD_PARAM_TYPE_POWER_1:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_2:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_3:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_4:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_5:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_6:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_7:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_8:
            *pValue = (float)(int16_t)param;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取1547参数
 */
funcInfErr_t FuncInf_Get1547Param(funcInf1547ParamType_t type, float *pValue)
{
    uint16_t addr, param;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_1547_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 780 + type;
    ParamTable_Get(addr, &param);

    switch(type)
    {
        case FUNCINF_1547_PARAM_TYPE_Q_MODE_SEL:
        case FUNCINF_1547_PARAM_TYPE_VP_MODE_EN:
        case FUNCINF_1547_PARAM_TYPE_FP_MODE_EN:
        case FUNCINF_1547_PARAM_TYPE_PL_MODE_EN:
            *pValue = (float)(int16_t)param;
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P3:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q3:
        case FUNCINF_1547_PARAM_TYPE_PQ_P2:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q2:
        case FUNCINF_1547_PARAM_TYPE_PQ_P1:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q1:
        case FUNCINF_1547_PARAM_TYPE_PQ_P1_N:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q1_N:
        case FUNCINF_1547_PARAM_TYPE_PQ_P2_N:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q2_N:
        case FUNCINF_1547_PARAM_TYPE_PQ_P3_N:
        case FUNCINF_1547_PARAM_TYPE_PQ_Q3_N:
        case FUNCINF_1547_PARAM_TYPE_VQ_V2:
        case FUNCINF_1547_PARAM_TYPE_VQ_Q2:
        case FUNCINF_1547_PARAM_TYPE_VQ_V1:
        case FUNCINF_1547_PARAM_TYPE_VQ_Q1:
        case FUNCINF_1547_PARAM_TYPE_VQ_V3:
        case FUNCINF_1547_PARAM_TYPE_VQ_Q3:
        case FUNCINF_1547_PARAM_TYPE_VQ_V4:
        case FUNCINF_1547_PARAM_TYPE_VQ_Q4:
        case FUNCINF_1547_PARAM_TYPE_VQ_TRESP:
        case FUNCINF_1547_PARAM_TYPE_VP_V1:
        case FUNCINF_1547_PARAM_TYPE_VP_P1:
        case FUNCINF_1547_PARAM_TYPE_VP_V2:
        case FUNCINF_1547_PARAM_TYPE_VP_P2:
        case FUNCINF_1547_PARAM_TYPE_VP_TRESP:
        case FUNCINF_1547_PARAM_TYPE_FP_PVAL:
        case FUNCINF_1547_PARAM_TYPE_FP_PMIN:
        case FUNCINF_1547_PARAM_TYPE_FP_TRESP:
        case FUNCINF_1547_PARAM_TYPE_PL_PMAX:
            *pValue = (float)(int16_t)param / 10;
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_UREF:
        case FUNCINF_1547_PARAM_TYPE_CPF_PF:
        case FUNCINF_1547_PARAM_TYPE_OV_2L:
        case FUNCINF_1547_PARAM_TYPE_OV_1L:
        case FUNCINF_1547_PARAM_TYPE_UV_1L:
        case FUNCINF_1547_PARAM_TYPE_UV_2L:
        case FUNCINF_1547_PARAM_TYPE_OV_2L_TIME:
        case FUNCINF_1547_PARAM_TYPE_OV_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UV_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UV_2L_TIME:
        case FUNCINF_1547_PARAM_TYPE_OF_2L:
        case FUNCINF_1547_PARAM_TYPE_OF_1L:
        case FUNCINF_1547_PARAM_TYPE_UF_1L:
        case FUNCINF_1547_PARAM_TYPE_UF_2L:
            *pValue = (float)(int16_t)param / 100;
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_DBUF:
        case FUNCINF_1547_PARAM_TYPE_FP_KUF:
        case FUNCINF_1547_PARAM_TYPE_FP_DBOF:
        case FUNCINF_1547_PARAM_TYPE_FP_KOF:
            *pValue = (float)(int16_t)param / 1000;
            break;

        case FUNCINF_1547_PARAM_TYPE_OF_2L_TIME:
        case FUNCINF_1547_PARAM_TYPE_OF_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UF_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UF_2L_TIME:
            *pValue = (float)(int16_t)param / 50;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取调试值
 */
funcInfErr_t FuncInf_GetDebugVal(funcInfDbgValIdx_t idx, float *pValue)
{
    uint16_t addr, dbg;

    switch(idx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_DBG_VAL_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 840 + idx;
    ParamTable_Get(addr, &dbg);

    *pValue = (float)(int16_t)dbg / 10;
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取时间
 */
funcInfErr_t FuncInf_GetTime(funcInfTimeType_t type, uint16_t *pValue)
{
    struct timeval tv;
    struct tm* pTm = NULL;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_TIME_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    gettimeofday(&tv, NULL);
    pTm = localtime (&tv.tv_sec);
    if(pTm == NULL)
    {
        PRINT_WARN();
        return -FUNCINF_ERR_READ;
    }

    switch(type)
    {
        case FUNCINF_TIME_TYPE_YEAR:
            *pValue = pTm->tm_year + 1900;
            break;

        case FUNCINF_TIME_TYPE_MON:
            *pValue = pTm->tm_mon + 1;
            break;
            
        case FUNCINF_TIME_TYPE_DATE:
            *pValue = pTm->tm_mday;
            break;
            
        case FUNCINF_TIME_TYPE_HOUR:
            *pValue = pTm->tm_hour;
            break;
            
        case FUNCINF_TIME_TYPE_MIN:
            *pValue = pTm->tm_min;
            break;
            
        case FUNCINF_TIME_TYPE_SEC:
            *pValue = pTm->tm_sec;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取额定功率
 */
funcInfErr_t FuncInf_GetRatedPwr(void *pParam, float *pValue)
{
    funcInfErr_t err;
    float pAcMax = 0.0F;

    if((err = FuncInf_GetExtremeValue(FUNCINF_EXTR_VAL_TYPE_AC_P_MAX, &pAcMax)) != 0)
    {
        return err;
    }

    *pValue = pAcMax / 1.3F;
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取绝缘板数据
 */
funcInfErr_t FuncInf_GetIsoBoardData(funcInfIsoBoardDataType_t type, float *pValue)
{
    int16_t data;
    isoBoardInfor_t isoBoardInfo;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_ISO_BOARD_DATA_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    GetIsoBoardInfor(&isoBoardInfo);

    switch(type)
    {
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_0:
            data = isoBoardInfo.temp[0];
            break;

        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_REACT:
            data = isoBoardInfo.temp[1];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_BUSCAP:
            data = isoBoardInfo.temp[2];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_3:
            data = isoBoardInfo.temp[3];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_TRANS:
            data = isoBoardInfo.temp[4];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_ACCBNT:
            data = isoBoardInfo.temp[5];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_FLTCAP2:
            data = isoBoardInfo.temp[6];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_TEMP_FLTCAP1:
            data = isoBoardInfo.temp[7];
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_UA:
            data = isoBoardInfo.volGridAB;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_UB:
            data = isoBoardInfo.volGridBC;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_UC:
            data = isoBoardInfo.volGridCA;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_RES_POS:
            data = isoBoardInfo.isoResPos;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_RES_NEG:
            data = isoBoardInfo.isoResNeg;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_IA:
            data = isoBoardInfo.curGridA;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_IB:
            data = isoBoardInfo.curGridB;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_IC:
            data = isoBoardInfo.curGridC;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_LEAK:
            data = isoBoardInfo.curLeak;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_VOL_POS:
            data = isoBoardInfo.isoVolPos;
            break;
            
        case FUNCINF_ISO_BOARD_DATA_TYPE_VOL_NEG:
            data = isoBoardInfo.isoVolNeg;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    *pValue = (float)data / 10.0F;
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 获取心跳
 */
funcInfErr_t FuncInf_GetHeartbeat(void *pParam, uint16_t *pValue)
{
    time_t sec;

    sec = time(NULL);
    *pValue = (sec & 0xFFFF);

    return FUNCINF_ERR_NONE;
}

/**
 * @brief 获取配置开关
 */
funcInfErr_t FuncInf_GetConfigSwitch(funcInfConfigSwitchType_t type, uint16_t *pValue)
{
    uint16_t addr = 718, strtg;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CONFIG_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    ParamTable_Get(addr, &strtg);

    if(type == FUNCINF_CONFIG_SWITCH_TYPE_ALL)
    {
        *pValue = strtg;
    }
    else
    {
        *pValue = GET_BIT(strtg, type);
    }
    
    return FUNCINF_ERR_NONE;
}
#endif


#if 1
/**
 * @brief 设置变比系数
 */
funcInfErr_t FuncInf_SetRatioCoef(funcInfOperator_t cmder, funcInfRatioCoefType_t type, float value)
{
    uint32_t addr, rc;
    
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_RATIO_COEF_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_RATIO_COEF_TYPE_NULL:
            return FUNCINF_ERR_NONE;

        case FUNCINF_RATIO_COEF_TYPE_AC_VOL:
            addr = 600;
            break;

        case FUNCINF_RATIO_COEF_TYPE_AC_CUR:
            addr = 602;
            break;

        case FUNCINF_RATIO_COEF_TYPE_AC_PWR:
            addr = 604;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_VOL:
            addr = 606;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_CUR:
            addr = 608;
            break;

        case FUNCINF_RATIO_COEF_TYPE_DC_PWR:
            addr = 610;
            break;

        case FUNCINF_RATIO_COEF_TYPE_BAT_VOL:
            addr = 612;
            break;

        case FUNCINF_RATIO_COEF_TYPE_POS_VOL:
            addr = 614;
            break;

        case FUNCINF_RATIO_COEF_TYPE_NEG_VOL:
            addr = 616;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    rc = (uint32_t)(value * 100000);
    UpperTable_Write(addr, rc & 0xFFFF);    
    UpperTable_Write(addr + 1, rc >> 16);
    ParamTable_Set(addr, rc & 0xFFFF);
    ParamTable_Set(addr + 1, rc >> 16);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1000 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %f", __func__, strCmder[cmder], strRatioCoefType[type], value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置网络参数
 */
funcInfErr_t FuncInf_SetNetParam(funcInfOperator_t cmder, funcInfNetParamType_t type, uint16_t value)
{
    PRINT_DEBUG();
    if(cmder == FUNCINF_OPERATOR_UPPER)
    {
        return FUNCINF_ERR_NONE;
    }

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_NET_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    if(value > 0xFF)
    {
        PRINT_WARN("Parameter error[%d]", value);
        return -FUNCINF_ERR_PARAM;
    }

    if(NetParam_Set((netParamType_t)type, value) != 0)
    {
        PRINT_WARN("Set failure");
        return -FUNCINF_ERR_WRITE;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1010 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strNetParamType[type], value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置HMI从机地址
 */
funcInfErr_t FuncInf_SetHmiSlaveId(funcInfOperator_t cmder, void *pParam, uint16_t value)
{   
    uint16_t addr = 690;

    UpperTable_Write(addr, value);
    ParamTable_Set(addr, value);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1050, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %d", __func__, strCmder[cmder], value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置最值
 */
funcInfErr_t FuncInf_SetExtremeValue(funcInfOperator_t cmder, funcInfExtrValType_t type, float value)
{
    uint16_t addr, extr;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_EXTR_VAL_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 700 + type;
    extr = (int16_t)value;
    UpperTable_Write(addr, extr);
    ParamTable_Set(addr, extr);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1060 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strExtrValType[type], (int16_t)value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置控制模式
 */
funcInfErr_t FuncInf_SetCtrlMode(funcInfOperator_t cmder, void *pParam, funcInfCtrlMode_t value)
{
    funcInfRunMode_t runMode;
    u16BitType_t mode;
    uint16_t idxLog, addr = 710;

    mode.u16Data = 0;

    if(value == FUNCINF_CTRL_MODE_LOCAL)
    {
        mode.bitData.b0 = 1;
        mode.bitData.b1 = 0;
        idxLog = 0;
    }
    else if(value == FUNCINF_CTRL_MODE_REMOTE)
    {
        mode.bitData.b0 = 0;
        mode.bitData.b1 = 1;
        idxLog = 1;
    }
    else
    {
        PRINT_WARN("Parameter error[%d]", value);
        return -FUNCINF_ERR_ENUM;
    }

    if(FuncInf_GetRunMode(NULL, &runMode) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Get failure");
        return -FUNCINF_ERR_READ;
    }

    switch(runMode)
    {
        case FUNCINF_RUN_MODE_PQ:
            mode.bitData.b8 = 1;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VF:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 1;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VSG:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 1;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_VI:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 1;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;
        
        case FUNCINF_RUN_MODE_CV:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 1;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_CC:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 1;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_CP:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 1;
            mode.bitData.b15 = 0;
            break;

        case FUNCINF_RUN_MODE_OL:
            mode.bitData.b8 = 0;
            mode.bitData.b9 = 0;
            mode.bitData.b10 = 0;
            mode.bitData.b11 = 0;
            mode.bitData.b12 = 0;
            mode.bitData.b13 = 0;
            mode.bitData.b14 = 0;
            mode.bitData.b15 = 1;
            break;
        
        default:
            PRINT_WARN("Out of enumeration[%d]", runMode);
            return -FUNCINF_ERR_ENUM;
    }

    UpperTable_Write(addr, mode.u16Data);
    ParamTable_Set(addr, mode.u16Data);
    TableRefresh_SendMessage(TABLE_MSGVAL_MODE);
    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1070 + idxLog, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %d", __func__, strCmder[cmder], value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置模式
 */
funcInfErr_t FuncInf_SetMode(funcInfOperator_t cmder, void *pParam, uint16_t value)
{
    uint16_t addr = 710, idxLog, modeTmp;
    funcInfRunMode_t runMode;
    u16BitType_t mode, modeCur, cmd1, cmd2;

    if(FuncInf_GetMode(NULL, &modeCur.u16Data) != FUNCINF_ERR_NONE)
    {
        PRINT_WARN("Get failure");
    }

    mode.u16Data = value ^ modeCur.u16Data;

    if((mode.bitData.b0 ^ mode.bitData.b1) == 0)
    {   
        if(mode.bitData.b8 == 1 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_PQ;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 1 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_VF;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 1 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_VSG;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 1  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_VI;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 1 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_CV;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 1  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_CC;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 1 && mode.bitData.b15 == 0)
        {
            runMode = FUNCINF_RUN_MODE_CP;
        }
        else if(mode.bitData.b8 == 0 && mode.bitData.b9 == 0 && \
            mode.bitData.b10 == 0 && mode.bitData.b11 == 0  && \
            mode.bitData.b12 == 0 && mode.bitData.b13 == 0  && \
            mode.bitData.b14 == 0 && mode.bitData.b15 == 1)
        {
            runMode = FUNCINF_RUN_MODE_OL;
        }
        else
        {
            PRINT_WARN("Out of enumeration: [%d][%d][%d]", mode.u16Data, value, modeCur.u16Data);
            return -FUNCINF_ERR_ENUM;
        }

        mode.bitData.b0 = modeCur.bitData.b0;
        mode.bitData.b1 = modeCur.bitData.b1;

        if(FuncInf_GetCmd(FUNCINF_CMD_IDX_1, &cmd1.u16Data) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }
        if(FuncInf_GetCmd(FUNCINF_CMD_IDX_2, &cmd2.u16Data) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }

        // PRINT_WARN("1-[0x%04X][0x%04X]", cmd1.u16Data, cmd2.u16Data);
        switch(runMode)
        {
            case FUNCINF_RUN_MODE_PQ:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 0;
                cmd1.bitData.b7 = 1;
                cmd2.bitData.b2 = 0;
                idxLog = 0;
                modeTmp = FUNCINF_RUN_MODE_PQ;
                break;

            case FUNCINF_RUN_MODE_VF:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 0;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 1;
                modeTmp = FUNCINF_RUN_MODE_VF;
                break;

            case FUNCINF_RUN_MODE_VSG:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 0;
                cmd1.bitData.b7 = 0;
                cmd2.bitData.b2 = 1;
                idxLog = 2;
                modeTmp = FUNCINF_RUN_MODE_VSG;
                break;

            case FUNCINF_RUN_MODE_VI:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 1;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 3;
                modeTmp = FUNCINF_RUN_MODE_VI;
                break;

            case FUNCINF_RUN_MODE_CV:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 1;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 4;
                modeTmp = FUNCINF_RUN_MODE_CV;
                break;

            case FUNCINF_RUN_MODE_CC:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 1;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 5;
                modeTmp = FUNCINF_RUN_MODE_CC;
                break;

            case FUNCINF_RUN_MODE_CP:
                cmd1.bitData.b5 = 0;
                cmd1.bitData.b6 = 1;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 6;
                modeTmp = FUNCINF_RUN_MODE_CP;
                break;

            case FUNCINF_RUN_MODE_OL:
                cmd1.bitData.b5 = 1;
                cmd1.bitData.b6 = 0;
                cmd1.bitData.b7 = 0;
                cmd1.bitData.b8 = 0;
                cmd2.bitData.b2 = 0;
                idxLog = 7;
                modeTmp = FUNCINF_RUN_MODE_OL;
                break;
            
            default:
                PRINT_WARN("Parameter error: [%d]", runMode);
                return -FUNCINF_ERR_PARAM;
        }
        // PRINT_WARN("2-[0x%04X][0x%04X]", cmd1.u16Data, cmd2.u16Data);

        if(FuncInf_SetCmd(cmder, FUNCINF_CMD_IDX_1, cmd1.u16Data) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Set failure");
            return -FUNCINF_ERR_WRITE;
        }
        if(FuncInf_SetCmd(cmder, FUNCINF_CMD_IDX_2, cmd2.u16Data) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Set failure");
            return -FUNCINF_ERR_WRITE;
        }
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 370 + idxLog, COM_DATA_TYPE_NONE, NULL);
        syslog(LOG_INFO, "%s: %s RunMode 0x%04X", __func__, strCmder[cmder], modeTmp);
    }
    else
    {   
        mode.bitData.b8 = modeCur.bitData.b8;
        mode.bitData.b9 = modeCur.bitData.b9;
        mode.bitData.b10 = modeCur.bitData.b10;
        mode.bitData.b11 = modeCur.bitData.b11;
        mode.bitData.b12 = modeCur.bitData.b12;
        mode.bitData.b13 = modeCur.bitData.b13;
        mode.bitData.b14 = modeCur.bitData.b14;
        mode.bitData.b15 = modeCur.bitData.b15;
        idxLog = mode.bitData.b0 == 1 ? 0 : 1;
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1070 + idxLog, COM_DATA_TYPE_NONE, NULL);
        idxLog = mode.bitData.b0 == 1 ? 1 : 2;
        syslog(LOG_INFO, "%s: %s CtrlMode %d", __func__, strCmder[cmder], idxLog);
    }
    
    UpperTable_Write(addr, mode.u16Data);
    ParamTable_Set(addr, mode.u16Data);
    TableRefresh_SendMessage(TABLE_MSGVAL_MODE);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置测试开关
 */
funcInfErr_t FuncInf_SetTestSwitch(funcInfOperator_t cmder, funcInfTestSwitchType_t type, uint16_t value)
{
    uint16_t addr = 712, test;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_TEST_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    if(type == FUNCINF_TEST_SWITCH_TYPE_ALL)
    {
        test = value;
    }
    else
    {
        if(FuncInf_GetTestSwitch(FUNCINF_TEST_SWITCH_TYPE_ALL, &test) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }
        value == 0 ? CLEAR_BIT(test, type) : SET_BIT(test, type);
    }

    UpperTable_Write(addr, test);
    ParamTable_Set(addr, test);
    if(type == FUNCINF_TEST_SWITCH_TYPE_ALL || \
       type == FUNCINF_TEST_SWITCH_TYPE_ALONE_TEST)
    {
        CommMonitor_SendMessage();
        Ieee1547_SendMessage();
    }

    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1090 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s 0x%04X", __func__, strCmder[cmder], strTestSwitchType[type], value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置通讯开关
 */
funcInfErr_t FuncInf_SetCommunicateSwitch(funcInfOperator_t cmder, funcInfCommSwitchType_t type, uint16_t value)
{
    uint16_t addr = 714, comm, i;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_COMM_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }
    
    if(type == FUNCINF_COMM_SWITCH_TYPE_ALL)
    {
        comm = value;
        for(i = 0; i < FUNCINF_COMM_SWITCH_TYPE_ALL; i++)
        {
            if(GET_BIT(comm, i) == 0)
            {
                CommMonitor_SetMonitorSwitch((commDevice_t)i, COMM_MONITOR_DISABLE);
            }
            else
            {
                CommMonitor_SetMonitorSwitch((commDevice_t)i, COMM_MONITOR_ENABLE);
            }
        }
    }
    else
    {
        if(FuncInf_GetCommunicateSwitch(FUNCINF_COMM_SWITCH_TYPE_ALL, &comm) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }

        if(value == 0)
        {
            CLEAR_BIT(comm, type);
            CommMonitor_SetMonitorSwitch((commDevice_t)type, COMM_MONITOR_DISABLE);
        }
        else
        {
            SET_BIT(comm, type);
            CommMonitor_SetMonitorSwitch((commDevice_t)type, COMM_MONITOR_ENABLE);
        }
    }

    UpperTable_Write(addr, comm);
    ParamTable_Set(addr, comm);
    CommMonitor_SendMessage();

    if(cmder != FUNCINF_OPERATOR_INIT)
    {
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1110 + type, COM_DATA_TYPE_NONE, NULL);
    }
    syslog(LOG_INFO, "%s: %s %s 0x%04X", __func__, strCmder[cmder], strCommSwitchType[type], value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置策略开关
 */
funcInfErr_t FuncInf_SetStrategySwitch(funcInfOperator_t cmder, funcInfStrtgSwitchType_t type, uint16_t value)
{
    uint16_t addr = 716, strtg;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_STRTG_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    if(type == FUNCINF_STRTG_SWITCH_TYPE_ALL)
    {
        strtg = value;
    }
    else
    {
        if(FuncInf_GetStrategySwitch(FUNCINF_STRTG_SWITCH_TYPE_ALL, &strtg) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }
        value == 0 ? CLEAR_BIT(strtg, type) : SET_BIT(strtg, type);
    }

    UpperTable_Write(addr, strtg);
    ParamTable_Set(addr, strtg);
    if(type == FUNCINF_STRTG_SWITCH_TYPE_ALL || \
       type == FUNCINF_STRTG_SWITCH_TYPE_1547)
    {
        Ieee1547_SendMessage();
    }

    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1130 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s 0x%04X", __func__, strCmder[cmder], strStrtgSwitchType[type], value);
    
    return FUNCINF_ERR_NONE;
}

/**
 * @brief 设置ARM阈值
 */
funcInfErr_t FuncInf_SetArmThrshd(funcInfOperator_t cmder, funcInfArmThrType_t type, float value)
{
    uint16_t addr, thrshd;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_ARM_THR_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_ARM_THR_TYPE_3L_OV_THR:
        case FUNCINF_ARM_THR_TYPE_3L_UV_THR:
        case FUNCINF_ARM_THR_TYPE_3L_OF_THR:
        case FUNCINF_ARM_THR_TYPE_3L_UF_THR:
            thrshd = (int16_t)value;
            addr = 770 + type; 
            break;

        case FUNCINF_ARM_THR_TYPE_3L_OV_TIME:
        case FUNCINF_ARM_THR_TYPE_3L_UV_TIME:
            thrshd = (int16_t)(value * 100);
            addr = 770 + type; 
            break;

        case FUNCINF_ARM_THR_TYPE_3L_OF_TIME:
        case FUNCINF_ARM_THR_TYPE_3L_UF_TIME:
            thrshd = (int16_t)(value * 50);
            addr = 770 + type; 
            break;

        case FUNCINF_ARM_THR_TYPE_HIG_TEMP_DERATE:
        case FUNCINF_ARM_THR_TYPE_TEMP_DIFF:
        case FUNCINF_ARM_THR_TYPE_LEAK_CUR:
            thrshd = (int16_t)value;
            addr = 720 + type - FUNCINF_ARM_THR_TYPE_HIG_TEMP_DERATE; 
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    UpperTable_Write(addr, thrshd);
    ParamTable_Set(addr, thrshd);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1150 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strArmThrType[type], (int16_t)value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置功率爬坡率
 */
funcInfErr_t FuncInf_SetPwrSloped(funcInfOperator_t cmder, void *pParam, float value)
{    
    uint16_t addr = 730, slope;

    slope = (int16_t)(value * 10);
    UpperTable_Write(addr, slope);
    ParamTable_Set(addr, slope);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1170, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %d", __func__, strCmder[cmder], (int16_t)value);

    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置时段参数
 */
funcInfErr_t FuncInf_SetPeriodParam(funcInfOperator_t cmder, funcInfPeriodParamType_t type, float value)
{
    uint16_t addr, param;

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_PERIOD_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_1:
        case FUNCINF_PERIOD_PARAM_TYPE_END_1:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_2:
        case FUNCINF_PERIOD_PARAM_TYPE_END_2:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_3:
        case FUNCINF_PERIOD_PARAM_TYPE_END_3:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_4:
        case FUNCINF_PERIOD_PARAM_TYPE_END_4:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_5:
        case FUNCINF_PERIOD_PARAM_TYPE_END_5:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_6:
        case FUNCINF_PERIOD_PARAM_TYPE_END_6:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_7:
        case FUNCINF_PERIOD_PARAM_TYPE_END_7:
        case FUNCINF_PERIOD_PARAM_TYPE_BEGIN_8:
        case FUNCINF_PERIOD_PARAM_TYPE_END_8:
            param = (int16_t)((value + 0.005) * 100); 
            PRINT_WARN("param = %d\n", param);
            //+0.005：排除类型转换导致小数丢失的问题，时段类小数只有两位小数，例如10.11在内存中可能是10.10999
            break;

        case FUNCINF_PERIOD_PARAM_TYPE_POWER_1:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_2:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_3:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_4:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_5:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_6:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_7:
        case FUNCINF_PERIOD_PARAM_TYPE_POWER_8:
            param = (int16_t)value;
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 740 + type; 
    UpperTable_Write(addr, param);
    ParamTable_Set(addr, param);

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1180 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strPeriodParamType[type], (int16_t)value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置1547参数
 */
funcInfErr_t FuncInf_Set1547Param(funcInfOperator_t cmder, funcInf1547ParamType_t type, float value)
{
    uint16_t addr, param, fpgaVal;

    ((void)(fpgaVal));

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_1547_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_1547_PARAM_TYPE_Q_MODE_SEL:
            param = (int16_t)value;
            /* 恒无功模式 */
            ((param >> 0) & 0x1) != 0 ? \
                Ieee1547_SetModeSwitch(MODE_CQ, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_CQ, MODE_SWITCH_OFF);
            /* 有功无功模式 */
            ((param >> 1) & 0x1) != 0 ? \
                Ieee1547_SetModeSwitch(MODE_PQ, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_PQ, MODE_SWITCH_OFF);
            /* 电压无功模式 */
            ((param >> 2) & 0x1) != 0 ? \
                Ieee1547_SetModeSwitch(MODE_VQ, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_VQ, MODE_SWITCH_OFF);
            /* 恒功率因数模式 */
            ((param >> 3) & 0x1) != 0 ? \
                Ieee1547_SetModeSwitch(MODE_CPF, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_CPF, MODE_SWITCH_OFF);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_MODE_EN:
            param = (int16_t)value;
            param != 0 ? \
                Ieee1547_SetModeSwitch(MODE_VP, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_VP, MODE_SWITCH_OFF);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_MODE_EN:
            param = (int16_t)value;
            param != 0 ? \
                Ieee1547_SetModeSwitch(MODE_FP, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_FP, MODE_SWITCH_OFF);
            break;

        case FUNCINF_1547_PARAM_TYPE_PL_MODE_EN:
            param = (int16_t)value;
            param != 0 ? \
                Ieee1547_SetModeSwitch(MODE_PL, MODE_SWITCH_ON) : \
                Ieee1547_SetModeSwitch(MODE_PL, MODE_SWITCH_OFF);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P3:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT3A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q3:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT3A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P2:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT2A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q2:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT2A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P1:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT1A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q1:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT1A);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P1_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT1B);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q1_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT1B);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P2_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT2B);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q2_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT2B);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_P3_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetActPwr((int16_t)param, PQ_POINT3B);
            break;

        case FUNCINF_1547_PARAM_TYPE_PQ_Q3_N:
            param = (int16_t)(value * 10);
            Ieee1547_ModePQ_SetReactPwr((int16_t)param, PQ_POINT3B);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_V2:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetVol(param, VQ_POINT2);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_Q2:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetReactPwr(param, VQ_POINT2);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_V1:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetVol(param, VQ_POINT1);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_Q1:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetReactPwr(param, VQ_POINT1);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_V3:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetVol(param, VQ_POINT3);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_Q3:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetReactPwr(param, VQ_POINT3);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_V4:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetVol(param, VQ_POINT4);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_Q4:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetReactPwr(param, VQ_POINT4);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_TRESP:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVQ_SetRespTime(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_V1:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVP_SetVol(param, VP_POINT1);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_P1:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVP_SetActPwr((int16_t)param, VP_POINT1);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_V2:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVP_SetVol(param, VP_POINT2);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_P2:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVP_SetActPwr((int16_t)param, VP_POINT2);
            break;

        case FUNCINF_1547_PARAM_TYPE_VP_TRESP:
            param = (int16_t)(value * 10);
            Ieee1547_ModeVP_SetRespTime(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_PVAL:
            param = (int16_t)(value * 10);
            Ieee1547_ModeFP_SetPavl(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_PMIN:
            param = (int16_t)(value * 10);
            Ieee1547_ModeFP_SetPmin(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_TRESP:
            param = (int16_t)(value * 10);
            Ieee1547_ModeFP_SetRespTime(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_PL_PMAX:
            param = (int16_t)(value * 10);
            Ieee1547_ModePL_SetPmax(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_VQ_UREF:
            param = (int16_t)(value * 100);
            Ieee1547_ModeVQ_SetVolRef(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_CPF_PF:
            param = (int16_t)(value * 100);
            Ieee1547_ModeCPF_SetPf((int16_t)param);
            break;

        case FUNCINF_1547_PARAM_TYPE_OV_2L:
            param = (int16_t)(value * 100);
            // if(FuncInf_DirectReadFpga(FPGA_ADDR_APPOINT_TYPE_AC_VOL, &fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            // fpgaVal = (uint16_t)(param / 100.0F * fpgaVal * 1.732 / 1.414);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L2_AC_OV, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_OV_1L:
            param = (int16_t)(value * 100);
            // if(FuncInf_DirectReadFpga(FPGA_ADDR_APPOINT_TYPE_AC_VOL, &fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            // fpgaVal = (uint16_t)(param / 100.0F * fpgaVal * 1.732 / 1.414);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L1_AC_OV, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_UV_1L:
            param = (int16_t)(value * 100);
            // if(FuncInf_DirectReadFpga(FPGA_ADDR_APPOINT_TYPE_AC_VOL, &fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            // fpgaVal = (uint16_t)(param / 100.0F * fpgaVal * 1.732 / 1.414);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L1_AC_UV, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_UV_2L:
            param = (int16_t)(value * 100);
            // if(FuncInf_DirectReadFpga(FPGA_ADDR_APPOINT_TYPE_AC_VOL, &fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            // fpgaVal = (uint16_t)(param / 100.0F * fpgaVal * 1.732 / 1.414);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L2_AC_UV, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_OV_2L_TIME:
            param = (int16_t)(value * 100);
            // fpgaVal = (uint16_t)(param * 10 * 0.0983477F);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L2_AC_OV_TIME, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_OV_1L_TIME:
            param = (int16_t)(value * 100);
            // fpgaVal = (uint16_t)(param * 10 * 0.0983477F);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L1_AC_OV_TIME, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_UV_1L_TIME:
            param = (int16_t)(value * 100);
            // fpgaVal = (uint16_t)(param * 10 * 0.0983477F);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L1_AC_UV_TIME, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_UV_2L_TIME:
            param = (int16_t)(value * 100);
            // fpgaVal = (uint16_t)(param * 10 * 0.0983477F);
            // if(FuncInf_DirectWriteFpga(cmder, FPGA_ADDR_THRSHD_TYPE_L2_AC_UV_TIME, fpgaVal) != FUNCINF_ERR_NONE)
            // {
            //     PRINT_WARN();
            //     break;
            // }
            break;

        case FUNCINF_1547_PARAM_TYPE_OF_2L:
        case FUNCINF_1547_PARAM_TYPE_OF_1L:
        case FUNCINF_1547_PARAM_TYPE_UF_1L:
        case FUNCINF_1547_PARAM_TYPE_UF_2L:
            param = (int16_t)(value * 100);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_DBUF:
            param = (int16_t)(value * 1000);
            Ieee1547_ModeFP_SetDbUf(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_KUF:
            param = (int16_t)(value * 1000);
            Ieee1547_ModeFP_SetKuf(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_DBOF:
            param = (int16_t)(value * 1000);
            Ieee1547_ModeFP_SetDbOf(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_FP_KOF:
            param = (int16_t)(value * 1000);
            Ieee1547_ModeFP_SetKof(param);
            break;

        case FUNCINF_1547_PARAM_TYPE_OF_2L_TIME:
        case FUNCINF_1547_PARAM_TYPE_OF_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UF_1L_TIME:
        case FUNCINF_1547_PARAM_TYPE_UF_2L_TIME:
            param = (int16_t)(value * 50);
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 780 + type;    
    UpperTable_Write(addr, param);
    ParamTable_Set(addr, param);

    if(cmder != FUNCINF_OPERATOR_INIT)
    {
        // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1210 + type, COM_DATA_TYPE_NONE, NULL);
        syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], str1547ParamType[type], (int16_t)value);
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置调试值
 */
funcInfErr_t FuncInf_SetDebugVal(funcInfOperator_t cmder, funcInfDbgValIdx_t idx, float value)
{
    uint16_t addr, dbg;

    switch(idx)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_DBG_VAL_IDX_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", idx);
            return -FUNCINF_ERR_PARAM;
    }

    addr = 840 + idx;
    dbg = (int16_t)(value * 10);  
    UpperTable_Write(addr, dbg);
    ParamTable_Set(addr, dbg);

    if(cmder != FUNCINF_OPERATOR_INIT)
    {
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1270 + idx, COM_DATA_TYPE_NONE, NULL);
    }
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strDbgValIdx[idx], (int16_t)value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置时间
 */
funcInfErr_t FuncInf_SetTime(funcInfOperator_t cmder, funcInfTimeType_t type, uint16_t value)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_TIME_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    switch(type)
    {
        case FUNCINF_TIME_TYPE_YEAR:
            if(value < 1970 || value > 2099)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_YEAR, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        case FUNCINF_TIME_TYPE_MON:
            if(value < 1 || value > 12)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_MON, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        case FUNCINF_TIME_TYPE_DATE:
            if(value < 1 || value > 31)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_DATE, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        case FUNCINF_TIME_TYPE_HOUR:
            if(value > 23)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_HOUR, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        case FUNCINF_TIME_TYPE_MIN:
            if(value > 59)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_MIN, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        case FUNCINF_TIME_TYPE_SEC:
            if(value > 59)
            {
                PRINT_WARN("Parameter error[%d]", value);
                return -FUNCINF_ERR_PARAM;
            }
            if(PopenInf_SetTime(POPENINF_TIME_TYPE_SEC, value) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    // logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1290 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s %d", __func__, strCmder[cmder], strTimeType[type], (int16_t)value);
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 重启
 */
funcInfErr_t FuncInf_Reboot(funcInfOperator_t cmder, void *pParam, void *pParam2)
{
    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1300, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s", __func__, strCmder[cmder]);
 
    if(NetParam_Update() != 0)
    {
        PRINT_WARN("Update failure");
        return -FUNCINF_ERR_WRITE;
    }

    if(PopenInf_Reboot() != 0)
    {
        PRINT_WARN("Reboot failure");
        return -FUNCINF_ERR_WRITE;
    }
    
    return FUNCINF_ERR_NONE;
}


/**
 * @brief 设置配置开关
 */
funcInfErr_t FuncInf_SetConfigSwitch(funcInfOperator_t cmder, funcInfConfigSwitchType_t type, uint16_t value)
{
    uint16_t addr = 718, config;
    char buf[10] = {0};

    switch(type)
    {
    #define X_MACRO(a, b) case a:
        FUNCINF_CONFIG_SWITCH_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    if(type == FUNCINF_CONFIG_SWITCH_TYPE_ALL)
    {
        config = value;
    }
    else
    {
        if(FuncInf_GetConfigSwitch(FUNCINF_CONFIG_SWITCH_TYPE_ALL, &config) != FUNCINF_ERR_NONE)
        {
            PRINT_WARN("Get failure");
            return -FUNCINF_ERR_READ;
        }
        value == 0 ? CLEAR_BIT(config, type) : SET_BIT(config, type);
    }

    UpperTable_Write(addr, config);
    ParamTable_Set(addr, config);

    switch (config)
    {
        case FUNCINF_CONFIG_SWITCH_TYPE_FAN_TYPE:
        {
            value == 0 ? strcpy(buf, "OLD_TYPE") : strcpy(buf, "NEW_TYPE");
            if(configInterface_SetConfig("modbus", "fan", "type", buf) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;
        }
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT1:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT2:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT3:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT4:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT5:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT6:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT7:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT8:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT9:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT10:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT11:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT12:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT13:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT14:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_BIT15:
            break;
        case FUNCINF_CONFIG_SWITCH_TYPE_ALL:
        {
            value == 0 ? strcpy(buf, "OLD_TYPE") : strcpy(buf, "NEW_TYPE");
            if(configInterface_SetConfig("modbus", "fan", "type", buf) != 0)
            {
                PRINT_WARN("Set failure");
                return -FUNCINF_ERR_WRITE;
            }
            break;
        }
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -FUNCINF_ERR_PARAM;
    }

    logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_OPERATOR_BEGIN + cmder, 1310 + type, COM_DATA_TYPE_NONE, NULL);
    syslog(LOG_INFO, "%s: %s %s 0x%04X", __func__, strCmder[cmder], strConfigSwitchType[type], value);
    
    return FUNCINF_ERR_NONE;
}

#endif
